package com.woniuxy.admin.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.admin.exception.AdminException;
import com.woniuxy.admin.exception.LoginException;
import com.woniuxy.admin.entity.AdminAccount;
import com.woniuxy.admin.form.*;
import com.woniuxy.admin.util.TokenUtil;
import com.woniuxy.core.annotation.Permission;
import com.woniuxy.core.exception.ParamException;
import com.woniuxy.core.util.Result;

;
import com.woniuxy.redis.util.RedisKey;
import com.woniuxy.redis.util.RedisUtil;
import com.woniuxy.admin.dto.AdminAccountDto;
import com.woniuxy.admin.dto.AdminAccountPageDto;


import com.woniuxy.admin.entity.AdminLogin;
import io.swagger.annotations.*;
import org.springframework.validation.BindingResult;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.woniuxy.admin.service.AdminAccountService;
import com.woniuxy.admin.service.AdminLoginService;
import com.woniuxy.admin.util.HttpUtils;
import com.woniuxy.admin.util.JWTUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author ...
 * @since 2024年05月22日
 */
@RestController
@RequestMapping("/adminAccount")
@Api(tags = "管理员账号")
public class AdminAccountController {

    @Resource
    private AdminAccountService adminAccountService;
    @Resource
    private AdminLoginService adminLoginService;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private TokenUtil tokenUtil;






    /**
     * 新增管理员账号
     * @param form 注册管理员的基本信息
     * @return
     * @throws InterruptedException
     */
    @ApiOperation("新增管理员账号")
    @PostMapping("/registAdmin")
    @Permission(roles = {"超级管理员"})
    public Result registAdmin(@RequestBody @Validated RegistAdminForm form, BindingResult brs) throws InterruptedException {
        if(brs.hasErrors()){
            throw new ParamException(10001,"参数异常");
        }
        adminAccountService.registAdmin(form);
    return Result.success("注册成功",null);
    }

    /**
     *
     * @param form 账号密码
     * @param req 请求对象拿到Ip地址分析登录地址
     * @param resp 登录成功响应token
     * @return
     */

    @ApiOperation("管理员账号密码登录")
    @PostMapping("/adminLogin")
    @ApiResponses({
            @ApiResponse(code = 200,message = "OK",response = AdminAccountDto.class)
    })
    public Result adminLogin( @RequestBody  AdminLoginForm form , HttpServletRequest req, HttpServletResponse resp) throws Exception {
        boolean flag = false;
        if(ObjectUtil.isEmpty(form.getAdminName())||ObjectUtil.isEmpty(form.getAdminPass())){
            flag=true;
        }
        if (flag) throw new Exception("参数异常");
        String s = redisUtil.get(RedisKey.AccountName(form.getAdminName()));
        System.out.println("1111");
        System.out.println(s);
        if (ObjectUtil.isNotEmpty(s)){
            System.out.println("222");
            System.out.println(s);
            redisUtil.del(s);
            System.out.println("333");
            System.out.println(RedisKey.AccountName(form.getAdminName()));
            redisUtil.del(RedisKey.AccountName(form.getAdminName()));
        }
        AdminAccountDto dto=adminAccountService.adminLogin(form);
        String remoteAddr = req.getRemoteAddr();
        String ipv6="";
        try {
            InetAddress address = InetAddress.getByName("::1"); // 本地IPv6地址，相当于IPv4的127.0.0.1
             ipv6 = address.getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String url = "http://whois.pconline.com.cn/ipJson.jsp";
        String ip =ipv6;
        String rspStr = null;
        String city=null;
        try {
            rspStr = HttpUtils.sendGet(url, "ip=" + ip + "&json=true", "GBK");
            JSONObject obj = JSONObject.parseObject(rspStr);
            city = obj.getString("city");
        } catch (Exception e) {
            System.out.println("***********************");
            rspStr = HttpUtils.sendGet(url, "ip=" + ip + "&json=true", "GBK");
            JSONObject obj = JSONObject.parseObject(rspStr);
            city = obj.getString("city");
        }
        AdminLogin adminLogin = new AdminLogin();
        adminLogin.setAdminName(dto.getAdminName());
        adminLogin.setLoginTime(LocalDateTime.now());
        adminLogin.setAddress(city);
        adminLogin.setIpAddress(remoteAddr);
        adminLoginService.save(adminLogin);
        Map<String, Object> map = BeanUtil.beanToMap(dto);
        HashMap<String, Object> accessBody=new HashMap<String, Object>();
        String random=new Snowflake(1,1).nextIdStr();
        accessBody.put("random",random);
        String accessToken= JWTUtil.createAdminToken(accessBody,3*24*60);
        String refreshToken=JWTUtil.createAdminToken(map,3*24*60);
        redisUtil.set(accessToken,refreshToken);
        redisUtil.set(RedisKey.AccountName(dto.getAdminName()),accessToken);
        resp.setHeader("token",accessToken);
        resp.setHeader("Access-Control-Expose-Headers","token");
        return Result.success("登录成功",dto);
    }

    /**
     *
     * @param form 手机号 验证码
     * @param req 通过请求对象拿到Ip地址分析登录地址
     * @param resp 登录成功响应token
     * @return
     */
    @ApiOperation("管理员验证码登录")
    @PostMapping("/adminCodeLogin")
    @ApiResponses({
            @ApiResponse(code = 200,message = "OK",response = AdminAccountDto.class)
    })
    public Result adminCodeLogin(@RequestBody AdminCodeLoginForm form, HttpServletRequest req, HttpServletResponse resp) throws Exception {
        boolean flag = false;
        if(ObjectUtil.isEmpty(form.getAdminPhone())||ObjectUtil.isEmpty(form.getAdminCode())){
            flag=true;
        }
        if (flag) throw new Exception("参数异常");
        AdminAccountDto dto=adminAccountService.adminCodeLogin(form);
        String remoteAddr = req.getRemoteAddr();
        String ipv6="";
        try {
            InetAddress address = InetAddress.getByName("::1"); // 本地IPv6地址，相当于IPv4的127.0.0.1
            ipv6 = address.getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String url = "http://whois.pconline.com.cn/ipJson.jsp";
        String ip =ipv6;
        String rspStr = HttpUtils.sendGet(url, "ip=" + ip + "&json=true", "GBK");
        JSONObject obj = JSONObject.parseObject(rspStr);
        String city = obj.getString("city");
        AdminLogin adminLogin = new AdminLogin();
        adminLogin.setAdminName(dto.getAdminName());
        adminLogin.setLoginTime(LocalDateTime.now());
        adminLogin.setAddress(city);
        adminLogin.setIpAddress(remoteAddr);
        adminLoginService.save(adminLogin);
        Map<String, Object> map = BeanUtil.beanToMap(dto);
        HashMap<String, Object> accessBody=new HashMap<String, Object>();
        String random=new Snowflake(1,1).nextIdStr();
        accessBody.put("random",random);
        String accessToken= JWTUtil.createAdminToken(accessBody,3*24*60);
        String refreshToken=JWTUtil.createAdminToken(map,3*24*60);
        System.out.println(refreshToken);
        redisUtil.set(accessToken,refreshToken);
        resp.setHeader("token",accessToken);
        resp.setHeader("Access-Control-Expose-Headers","token");
        return Result.success("登录成功",dto);
    }


    /**
     * 发送管理员登录验证码
     * @param adminPhone 手机号
     * @return
     */
    @ApiOperation("发送管理员登录验证码")
    @GetMapping("/sendAdminLoginCode")
    @ApiImplicitParam(name = "adminPhone",value ="手机号" )
    public Result sendAdminLoginCode(String adminPhone){
        adminAccountService. sendAdminLoginCode(adminPhone);
        return Result.success("发送验证码成功,注意查收",null);
    }

    /**
     * 分页查询所有管理员账号
     * @param pageNum
     * @param pageSize
     * @param condition
     * @return
     */
    @ApiOperation("查询所有管理员账号")
    @GetMapping("/loadAllAdminAccount")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum",value ="当前页码" ),
            @ApiImplicitParam(name = "pageSize",value ="每页几条" ),
            @ApiImplicitParam(name = "condition",value ="查询条件" )
    })
    @ApiResponses({
            @ApiResponse(code = 200,message = "OK",response = AdminAccountPageDto.class)
    })
    public Result loadAllAdminAccount(Integer pageNum,Integer pageSize,String condition){
        Page<AdminAccountPageDto> pages=adminAccountService.loadAllAdminAccount(pageNum,pageSize,condition);
        return Result.success("查询所有账号成功",pages);
    }

    /**
     * 更新管理员状态
     * @param accountId 管理员Id
     * @param state 状态
     * @return
     */
    @GetMapping("/updateAdminAccountState")
    @ApiOperation("更新管理员状态")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "accountId",value ="管理员账号" ),
            @ApiImplicitParam(name = "state",value ="管理员状态" )
    })
    @Permission(roles = {"超级管理员"})
    public Result updateAdminAccountState(Integer accountId,Integer state,@RequestHeader String token) throws Exception {
        Integer id = tokenUtil.getAccountId(token);
        if(id==accountId) throw new AdminException(10002,"不能自己更新自己");
        if(state!=0&&state!=1) throw new AdminException(10002,"状态有误");
        adminAccountService.updateAdminAccountState(accountId,state);
        return Result.success("更新成功",null);
    }

    /**
     * 根据角色Id 查询账号Id集合
     * @param roleId
     * @return
     */
    @ApiOperation("根据角色Id 查询账号Id集合")
    @GetMapping("/selectAccountsByRoleId")
    @ApiImplicitParam(name = "roleId",value ="角色ID")
    @Permission(roles = {"超级管理员"})
    public Result selectAccountsByRoleId(Integer roleId){
    List<Integer> accounts= adminAccountService.selectAccountsByRoleId(roleId);
    return Result.success("根据角色Id查询账号集合成功",accounts);
    }


    /**
     * 根据角色Id 查询账号详情
     * @param roleId
     * @return
     */
    @ApiOperation("根据角色Id 查询账号详情")
    @GetMapping("/selectAccountInfoByRoleId")
    @ApiImplicitParam(name = "roleId",value ="角色ID")
    public Result selectAccountInfoByRoleId(Integer roleId){
        List<AdminAccountPageDto>list=adminAccountService.selectAccountInfoByRoleId(roleId);
        return Result.success("查询成功",list);
    }

    /**
     * 发送管理修改手机短信
     * @return
     */
    @GetMapping("/sendAdminUpdatePhone")
    @ApiOperation("发送管理修改手机短信")
    @ApiImplicitParam(name ="adminPhone" ,value ="管理手机号" )
    public Result sendAdminUpdatePhone(@RequestHeader String token, String adminPhone){
        Integer accountId = tokenUtil.getAccountId(token);
        adminAccountService.sendAdminUpdatePhone(accountId,adminPhone);
        return Result.success("发送用户修改手机短信",null);
    }

    /**
     * 验证管理修改手机短信
     * @param adminPhone
     * @param adminCode
     * @return
     */
    @GetMapping("/checkAdminUpdatePhone")
    @ApiOperation("验证管理修改手机短信")
    @ApiImplicitParams({
            @ApiImplicitParam(name ="adminPhone" ,value ="管理手机号" ),
            @ApiImplicitParam(name ="adminCode" ,value ="管理验证码" )
    })
    public Result checkAdminUpdatePhone(String adminPhone,String adminCode){
        if (redisUtil.hasKey(RedisKey.codeErrorNumber(adminPhone))) {
            if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(adminPhone)))) >= 5) {
                throw new LoginException(10002, "验证码已错5次,请重新发送");
            }
        }
        if (!adminCode.equals(redisUtil.get(RedisKey.AdminUpdatePhoneCodeKey(adminPhone)))) {
            if (redisUtil.hasKey(RedisKey.codeErrorNumber(adminPhone))) {
                redisUtil.insr(RedisKey.codeErrorNumber(adminPhone));
                if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(adminPhone)))) >= 5) {
                    redisUtil.del(RedisKey.AdminUpdatePhoneCodeKey(adminPhone));
                }
            } else {
                redisUtil.set(RedisKey.codeErrorNumber(adminPhone), "1", 5 * 60);
            }
            throw new LoginException(10001, "手机验证码错误");
        }
       return Result.success("验证成功",adminCode);
    }

    /**
     * 发送管理修改新手机短信
     * @return
     */
    @GetMapping("/sendAdminUpdateNewPhone")
    @ApiOperation("发送管理修改新手机短信")
    @ApiImplicitParam(name ="adminPhone" ,value ="管理手机号" )
    public Result sendAdminUpdateNewPhone(@RequestHeader String token, String adminPhone){
        Integer accountId = tokenUtil.getAccountId(token);
        adminAccountService.sendAdminUpdateNewPhone(accountId,adminPhone);
        return Result.success("发送管理修改新手机短信",null);
    }

    /**
     * 管理修改手机号
     * @param token
     * @param form
     * @return
     */
    @PostMapping("/adminUpdatePhone")
    @ApiOperation("管理修改手机号")
    public Result adminUpdatePhone(@RequestHeader String token,@RequestBody AdminUpdatePhoneForm form){
        Integer accountId = tokenUtil.getAccountId(token);
        adminAccountService.adminUpdatePhone(accountId,form);
        return Result.success("修改手机号成功",null);
    }

    /**
     * 修改密码
     * @param token
     * @param form
     * @return
     */
    @PostMapping("/adminUpdatePass")
    @ApiOperation("修改密码")
    public Result adminUpdatePass(@RequestHeader String token, @RequestBody AdminUpdatePassForm form){
        System.out.println(form);
        Integer accountId = tokenUtil.getAccountId(token);
        System.out.println(accountId);
        adminAccountService.adminUpdatePass(accountId,form);
        return Result.success("修改密码成功",null);
    }

    /**
     * 查询refreshToken
     * @param token
     * @return
     */
    @GetMapping("/selectToken")
    @ApiOperation("查询refreshToken")
    public Result selectToken(String token){
        String refreshToken = redisUtil.get(token);
        if(refreshToken==null) throw new AdminException(1001,"token不存在");
        return Result.success("查询token成功",refreshToken);
    }

    /**
     * 根据用户名查找账户信息
     * @param adminName 用户名
     * @return 管理员信息
     */
    @GetMapping("/selectAccountByAdminName")
    @ApiOperation("根据用户名查找账户信息")
    @ApiImplicitParam("用户名")
    public Result selectAccountByAdminName(String adminName){
        AdminAccount account = adminAccountService.selectAccountByAdminName(adminName);
        return Result.success("根据用户名查找账户信息成功",account);
    }
}

